gRPC实现跨语言(golang&&java)服务调用

您所在的位置:网站首页 golang rpc 多client gRPC实现跨语言(golang&&java)服务调用

gRPC实现跨语言(golang&&java)服务调用

#gRPC实现跨语言(golang&&java)服务调用| 来源: 网络整理| 查看: 265

为何RPC

在微服务这个时代,不论是传输还是内网调用,以及跨语言的传输,RPC都是不二的选择。GRPC是Google基于protocol buffer传输协议开发的一个RPC框架,支持多语言之间的通信,下面,我会基于Java语言和golang语言做一个跨语言调用例子,Java做client端,golang做服务端

计算器proto接口定义: syntax = "proto3"; option go_package = "client"; //请求 message Request { double num1 = 1; double num2 = 2; OperateType opType = 3; } //操作类型 enum OperateType { Addition = 0; Division = 1; Multiplication = 2; Subtraction = 3; } message Response { double result = 1; } //定义服务 service Operate { rpc Calculate (Request) returns (Response); } 生成go源码:

官方给go语言的生成提供了插件,用这个命令就可以快速生成go端的相关代码,为了简便期间,我写成了一个简单的脚本:

#!/usr/bin/env bash find ./ -name '*.proto'|xargs protoc --go_out=plugins=grpc:.

这个脚本的作用是寻找当前文件下的所有proto文件,并在其所在文件夹下生成源码 在这里插入图片描述

编写server端:

接口:

package main import ( "context" "errors" "google.golang.org/grpc" "log" "net" "testgo/proto" "testgo/service" ) const ( port = ":9543" ) type server struct { } func (server) Calculate(ctx context.Context, in *client.Request) (resp *client.Response, e error) { log.Printf("Received request") defer func() { // 必须要先声明defer,否则不能捕获到panic异常 if err := recover(); err != nil { e = errors.New(err.(string)) // 这里的err其实就是panic传入的内容 } }() c := service.Calculate{Num1: in.Num1, Num2: in.Num2,} var result float64 switch in.OpType { case client.OperateType_Addition: result = c.Operate(service.Addition) case client.OperateType_Division: result = c.Operate(service.Division) case client.OperateType_Multiplication: result = c.Operate(service.Multiplication) case client.OperateType_Subtraction: result = c.Operate(service.Subtraction) } return &client.Response{Result: result,}, nil } func main() { lis, err := net.Listen("tcp", port) if err != nil { log.Fatalf("failed to listen: %v", err) } s := grpc.NewServer() client.RegisterOperateServer(s, &server{}) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } }

业务代码:

package service type Calculate struct { Num1 float64 Num2 float64 } type Operate func(num1, num2 float64) (result float64) //操作接口 func (c Calculate) Operate(op Operate) (result float64) { return op(c.Num1, c.Num2) } package service //定义操作类型 func Addition(num1, num2 float64) (result float64) { return num1 + num2 } func Division(num1, num2 float64) (result float64) { if num2 == 0 { panic("division by zero") } return num1 / num2 } func Multiplication(num1, num2 float64) (result float64) { return num1 * num2 } func Subtraction(num1, num2 float64) (result float64) { return num1 - num2 }

如果server端代码有问题的童鞋,可以参考go官方的rpc调用example

编写go client端 package main import ( "context" "google.golang.org/grpc" "log" "testgo/proto" "time" ) const ( address = "localhost:9543" ) func main() { // Set up a connection to the server. conn, err := grpc.Dial(address, grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := client.NewOperateClient(conn) // Contact the server and print out its response. ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() r, err := c.Calculate(ctx, &client.Request{Num1: 1, Num2: 0, OpType: client.OperateType_Division}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("result: %f", r.Result) } 实现java client端: 引入gprc的maven依赖: io.grpc grpc-netty-shaded 1.20.0 io.grpc grpc-protobuf 1.20.0 io.grpc grpc-stub 1.20.0 引入编译proto文件的maven插件: kr.motd.maven os-maven-plugin 1.5.0.Final org.xolstice.maven.plugins protobuf-maven-plugin 0.5.1 com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier} grpc-java io.grpc:protoc-gen-grpc-java:1.20.0:exe:${os.detected.classifier} compile compile-custom

运行命令:mvn clean install 在这里插入图片描述 可以看见相关的文件已经生成

编写java Client端: package com.tangbaobao.rpc.service; import com.tangbaobao.client.Calcualte; import com.tangbaobao.client.OperateGrpc; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.concurrent.TimeUnit; /** * @author tangxuejun * @version 2019-04-16 11:25 */ public class CalculateService { private final ManagedChannel channel; private final OperateGrpc.OperateBlockingStub blockingStub; private CalculateService(ManagedChannel channel) { this.channel = channel; blockingStub = OperateGrpc.newBlockingStub(channel); } public CalculateService(String host, int port) { this(ManagedChannelBuilder.forAddress(host, port) .usePlaintext() .build()); } public void shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } public float operate(float num1, float num2, Calcualte.OperateType operateType) { Calcualte.Request request = Calcualte.Request.newBuilder().setNum1(num1).setNum2(num2).setOpType(operateType).build(); Calcualte.Response response = blockingStub.calculate(request); return (float) response.getResult(); } public static void main(String[] args) { try { CalculateService service = new CalculateService("localhost", 9543); System.out.println(service.operate(100, 0, Calcualte.OperateType.Division)); service.shutdown(); } catch (Exception e) { System.out.println(e); } } } 运行结果

先启动server端: 然后启动client端

在这里插入图片描述

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3